﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SortGuid.Tool.Comb.Strategy
{
    public class SqlDateTimeStrategy : ICombDateTimeStrategy
    {
        private const double TicksPerDay = 25920000.0;

        private const double TicksPerMillisecond = 0.3;

        private int _numDateBytes = 6;

        public int NumDateBytes
        {
            get { return _numDateBytes; }
        }

        private DateTime _minDateTimeValue = new DateTime(1900, 1, 1);

        public DateTime MinDateTimeValue
        {
            get { return _minDateTimeValue; }
        }

        private DateTime _maxDateTimeValue = new DateTime(1900, 1, 1).AddDays(65535.0);

        public DateTime MaxDateTimeValue
        {
            get { return _maxDateTimeValue; }
        }

        public byte[] DateTimeToBytes(DateTime timestamp)
        {
            int value = (int)(timestamp.TimeOfDay.TotalMilliseconds * 0.3);
            ushort value2 = (ushort)(timestamp - MinDateTimeValue).TotalDays;
            byte[] bytes = BitConverter.GetBytes(value);
            byte[] bytes2 = BitConverter.GetBytes(value2);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse((Array)bytes2);
                Array.Reverse((Array)bytes);
            }

            byte[] array = new byte[NumDateBytes];
            Array.Copy(bytes2, 0, array, 0, 2);
            Array.Copy(bytes, 0, array, 2, 4);
            return array;
        }

        public DateTime BytesToDateTime(byte[] value)
        {
            byte[] array = new byte[2];
            byte[] array2 = new byte[4];
            Array.Copy(value, 0, array, 0, 2);
            Array.Copy(value, 2, array2, 0, 4);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse((Array)array);
                Array.Reverse((Array)array2);
            }

            ushort num = BitConverter.ToUInt16(array, 0);
            int num2 = BitConverter.ToInt32(array2, 0);
            if ((float)num2 < 0f)
            {
                throw new ArgumentException("Not a COMB, time component is negative.");
            }

            if ((double)num2 > 25920000.0)
            {
                throw new ArgumentException("Not a COMB, time component exceeds 24 hours.");
            }

            return MinDateTimeValue.AddDays((int)num).AddMilliseconds((double)num2 / 0.3);
        }
    }
}
